from feature_data.const_data import *
from feature_data.XmlData2DictData import Xml2Dict
from feature_data.Dict2Venue_Graphfeature import Feature_venue_extration
from nd_service.third_stage_graph import Graph_venue_stage

from nd_utils.vec_similarity import set_jaccrd


# https://blog.csdn.net/xiaqian0917/article/details/53445071

# macro micro https://blog.csdn.net/Leoch007/article/details/80684464
class Pairwise_Metric():
    def __init__(self, xml2dict):
        self.xml2dict = xml2dict

        self.publication_dict = self.xml2dict.publication_dict
        self.paperid_idx_dict = self.xml2dict.paperid_idx_dict
        self.idx_paperid_dict = self.xml2dict.idx_paperid_dict

        self.labelset_list = self._get_labelset_list()
        self.paper_label_dict = self._get_paper_label_dict()

        self.true_label_dict = self._get_label_inverse_table()
        #########################################
        self.true_cluster_list = self.true_label_dict.values()
        self.predict_cluster_list = self._get_cluster_list()

        self.true_pairwise_set_list = self._get_pairwise_set_list(self.true_cluster_list)
        self.predict_pairwise_set_list = self._get_pairwise_set_list(self.cluster_set_2_list())

        self.tp_plus_fn = len(self.true_pairwise_set_list)
        self.tp_plus_fp = len(self.predict_pairwise_set_list)
        self.tp = self._get_tp()

    """
        idx : label
    """

    def _get_paper_label_dict(self):
        paper_label_dict = {}
        for paperid, publication_attr_dict in self.publication_dict.items():
            paper_label_dict[self.paperid_idx_dict[paperid]] = publication_attr_dict['label']
        return paper_label_dict

    """
        all label set
    """

    def _get_labelset_list(self):
        label_set = set()
        for publication_attr_dict in self.publication_dict.values():
            label_set.add(publication_attr_dict['label'])
        return list(label_set)

    def _get_label_inverse_table(self):
        label_idx_dict = {}
        for paper_idx, paper_label in self.paper_label_dict.items():
            if paper_label not in label_idx_dict:
                label_idx_dict[paper_label] = [paper_idx]
            else:
                label_idx_dict[paper_label].append(paper_idx)
        return label_idx_dict

    def _get_cluster_list(self):
        feature_venue_extration = Feature_venue_extration(self.xml2dict)
        third_stage_clust = Graph_venue_stage(feature_venue_extration)
        return third_stage_clust.cluster_list


    def cluster_set_2_list(self):
        cluster_set_list = list(self.predict_cluster_list)
        idx_list_list = []
        for cluster in cluster_set_list:
            idx_list_list.append(list(cluster))
        return idx_list_list

    def _get_pairwise_set_list(self, cluster_list):
        cluster_set_list = []
        for cluster in cluster_list:
            if len(cluster) > 1:
                for i in range( len(cluster)-1 ):
                    for j in range( i+1, len(cluster) ):
                        set1 =  set([ cluster[i] , cluster[j]])
                        cluster_set_list.append( set1 )
            else:
                cluster_set_list.append( set(cluster) )
        return cluster_set_list

    def is_set_equal(self, pairset1, pairset2):
        if pairset1.issubset(pairset2) and pairset2.issubset(pairset1):
            return True
        else:
            return False

    def _get_tp(self):
        tp = 0
        for set1 in self.true_pairwise_set_list:
            for set2 in self.predict_pairwise_set_list:
                if self.is_set_equal(set1, set2):
                    tp += 1
                    break
        return tp

    # p : 3p
    def get_pairwise_precision(self):
        return float(self.tp) / self.tp_plus_fp

    # p : 2p1n
    def get_pairwise_recall(self):
        return float(self.tp) / self.tp_plus_fn

    def get_pairwise_f1(self):
        precision = self.get_pairwise_precision()
        recall = self.get_pairwise_recall()
        return float(2 * precision * recall) / (precision + recall)


def print_dict(label_dict):
    for label, idx_list in label_dict.items():
        print idx_list


def print_paperid(f1):
    """
     1
     list1 = [6, 32, 50]
    list2 = [0, 39, 47, 57]
    list3 = [10, 35, 46, 63, 75]
    list4 = [27, 37, 42, 53, 58, 65, 73, 82, 96, 98]
    list5 = [95]
    list_set = [list1, list2, list3, list4, list5]

    """

    """

    """
    list1 = [9, 14, 44, 85]
    list2 = [11]

    list_set = [list1, list2]
    for ls in list_set:
        paperid_ls = []
        for idx in ls:
            paperid_ls.append(f1.idx_paperid_dict[idx])
        print paperid_ls

def print_pairwise_f1():
    xml_file_name_list = [
        xml_file_name1,
        xml_file_name2,
        xml_file_name3,
        xml_file_name4,
        xml_file_name5,
        xml_file_name6,
        xml_file_name7,
        xml_file_name8,
        xml_file_name9,
        xml_file_name10
    ]
    for xml_file_name in xml_file_name_list:
        xml2dict = Xml2Dict(xml_dir + xml_file_name)
        metric = Pairwise_Metric(xml2dict)

        # print metric.tp_plus_fp

        # print metric.tp_plus_fn

        print xml_file_name, metric.get_pairwise_precision(), metric.get_pairwise_recall(), metric.get_pairwise_f1()


def print_pairwise_f1_7():
    xml2dict = Xml2Dict(xml_dir + xml_file_name7)
    metric = Pairwise_Metric(xml2dict)

    print metric.tp_plus_fp

    print metric.tp_plus_fn

    print xml_file_name7, metric.get_pairwise_precision(), metric.get_pairwise_recall(), metric.get_pairwise_f1()

if __name__ == '__main__':
    print_pairwise_f1()

    # print_pairwise_f1_7()


"""
Jing Zhang.xml 0.911487758945 0.506276150628 0.650975117687
Bin Yu.xml 0.942028985507 0.347222222222 0.507416081187
Rakesh Kumar.xml 0.993783993784 0.815168897387 0.895658263305
Lei Wang.xml 0.796296296296 0.719521912351 0.755964838845
Bin Li.xml 0.988286969253 0.790398126464 0.878334417697
Yang Wang.xml 0.852272727273 0.31017369727 0.454821103699
Bo Liu.xml 0.97052154195 0.981651376147 0.976054732041
Yu Zhang.xml 0.917543859649 0.473731884058 0.624850657109
David Brown.xml 0.991452991453 0.978902953586 0.985138004246
Wei Xu.xml 0.949464012251 0.676855895197 0.790312300829
"""